/*
 * Copyright(c) 2020 Jesse Kuang  <jkuang@21cn.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *  * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once
#ifndef __ECC_H__
#define __ECC_H__

// Revised for rust-lang bindings
// striped from golang version ecc.h
#include "cdefs.h"

/* One digit is u64 qword. */

#ifdef	__cplusplus
extern "C" {
#endif

/**
 * ecc_make_pub_key() - Compute an ECC public key
 *
 * @curve_id:		id representing the curve to use
 * @ndigits:		curve's number of digits
 * @private_key:	pregenerated private key for the given curve
 * @public_key:		buffer for storing the generated public key
 *
 * Returns 0 if the public key was generated successfully, a negative value
 * if an error occurred.
 */
int ecc_make_pub_key(const u64 *private_key, u64 *public_key);

/**
 * vli_mod_inv() - Modular inversion
 *
 * @result:		where to write vli number, 256 Bits
 * @input:		vli value to operate on
 * @mod:		modulus
 * @ndigits:		length of all vlis
 */
void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod);

/*
 * vli_sm2p_mod
 * vli_sm2p_reduction
 * mont_sm2_mod_mult_p
 * mont_sm2_mod_mult_n
 */
void vli_sm2p_mod(u64 *result, const u64 *left, const bool carry);
void vli_sm2p_reduction(u64 *result, const u64 *y);
void vli_sm2p_mod_mult(u64 *result, const u64 *x, const u64 *y);
void vli_sm2p_sqr(u64 *result, const u64 *x);
// mont_sm2_mod_mult_n result = x * y, result is reductioned
void mont_sm2_mod_mult_n(u64 *result, const u64 *x, const u64 *y);
void to_mont_sm2_n(u64 *result, const u64 *x);


/**
 * get_curve_params	--	get curve params
 * p, n, b, gx, gy	--	bn_t 256 Bits
 */
void	get_curve_params(u64 *p, u64 *n, u64 *b, u64 *gx, u64 *gy);
void	point_double_jacobian(Point *pt, const Point *p);
void	point_add_jacobian(Point *pt, const Point *p, const Point *q);
void	point_double(Point *pt, const Point *p);
void	point_add(Point *pt, const Point *p, const Point *q);
void	point_mult(Point *pt, const Point *p, const u64 *scalar);
void	point_cmult(Point *pt, const Point *p, const u64 *scalar,
				const u64 *gscalar);
void	affine_from_jacobian(u64 *x, u64 *y, const Point *pt);
int		ecc_verify(const u64 *rP, const u64 *sP, const u64 *msgP,
				const u64 *pubx, const u64 *puby);
int		ecc_sign(u64 *rP, u64 *sP, const u64 *msgP, const u64 *privKey);
int		ecc_recover(const u64 *rP, const u64 *sP, const u64 *msgP, const u64 v,
				u64 *px, u64 *py);
int		point_recoverY(u64 *y1, const u64 *x1, const uint isOdd);

#ifdef	__cplusplus
}
#endif

#endif	//	__ECC_H__
